package com.oos.zone.wechat.ma.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaMessage;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import com.oos.zone.wechat.ma.service.WechatMaEventNoticeService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 功能描述：微信小程序消息事件处理
 *
 * @author 拓金辉
 * @version 1.0
 * @date 2021-08-11 19:11:26
 */
@Log4j2
@Service
public class WechatMaEventNoticeServiceImpl implements WechatMaEventNoticeService {

    @Resource
    private WxMaMessageRouter wxMaMessageRouter;

    @Resource
    private WxMaService wxMaService;

    public String notice(String signature, String timestamp, String nonce, String openId, String encryptType, String msgSignature, String appId, HttpServletRequest request) {
        try (ServletInputStream inputStream = request.getInputStream()) {
            String original = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
            WxMaService wxMaService = this.wxMaService.switchoverTo(appId);
            WxMaConfig wxMaConfig = wxMaService.getWxMaConfig();

            if (!wxMaService.checkSignature(timestamp, nonce, signature)) {
                throw new RuntimeException("验证消息来自微信服务器验证失败");
            }

            if (Objects.isNull(encryptType) && Objects.isNull(msgSignature)) {
                WxMaMessage wxMaMessage = WxMaMessage.fromXml(original);

                WxMaXmlOutMessage wxMaXmlOutMessage = wxMaMessageRouter.route(wxMaMessage);
                return Objects.isNull(wxMaXmlOutMessage) ? "success" : wxMaXmlOutMessage.toXml();
            } else {
                WxMaMessage wxMaMessage = WxMaMessage.fromEncryptedXml(original, wxMaConfig, timestamp, nonce, msgSignature);
                WxMaXmlOutMessage wxMaXmlOutMessage = wxMaMessageRouter.route(wxMaMessage);
                return Objects.isNull(wxMaXmlOutMessage) ? "success" : wxMaXmlOutMessage.toEncryptedXml(wxMaConfig);
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            WxMaConfigHolder.remove();
        }
    }

    public String notice(String signature, String timestamp, String nonce, String echoStr, String appId, HttpServletRequest request) {
        try {
            final WxMaService wxMaService = this.wxMaService.switchoverTo(appId);
            return wxMaService.checkSignature(timestamp, nonce, signature) ? new WxMaCryptUtils(wxMaService.getWxMaConfig()).encrypt(echoStr) : "验签失败";
        } finally {
            WxMaConfigHolder.remove();
        }
    }

}
